<template>
  <el-popover
    :placement="placement"
    trigger="focus"
    :hide-after="0"
    :width="state.selectorWidth"
    :visible="state.popoverVisible"
  >
    <div
      @mouseover.stop="state.iconSelectorMouseover = true"
      @mouseout.stop="state.iconSelectorMouseover = false"
      class="icon-selector"
    >
      <div class="icon-selector-box">
        <div class="selector-header">
          <div class="selector-title">请选择图标</div>
          <div class="selector-tab">
            <span
              v-for="iconType in tabsList"
              :key="iconType.name"
              :title="iconType.label"
              @click="onChangeTab(iconType.name)"
              :class="currentActiveType == iconType.name ? 'active' : ''"
            >
              {{ iconType.label }}
            </span>
          </div>
        </div>
        <div class="selector-body">
          <el-scrollbar ref="selectorScrollbarRef">
            <div
              class="icon-selector-item"
              :title="item"
              @click="onIcon(item)"
              v-for="(item, key) in pageList"
              :key="key"
            >
              <IconifyIconOnline :icon="currentActiveType + item" />
            </div>
          </el-scrollbar>
        </div>
      </div>
    </div>
    <template #reference>
      <el-input
        v-model="filterValue"
        :size="size"
        :disabled="disabled"
        placeholder="搜索图标"
        ref="selectorInput"
        @focus="onInputFocus"
        @blur="onInputBlur"
        :class="'size-' + size"
      >
        <template #prepend>
          <div class="icon-prepend">
            <IconifyIconOnline :icon="state.iconType + state.prependIcon" />
            <div v-if="showIconName" class="name">
              {{
                state.prependIcon
                  ? state.iconType + state.prependIcon
                  : state.defaultModelValue
              }}
            </div>
          </div>
        </template>
        <template #append>
          <IconifyIconOnline @click="onInputRefresh" icon="ep:refresh" />
        </template>
      </el-input>
    </template>
  </el-popover>
</template>

<script setup lang="ts">
import { reactive, ref, onMounted, nextTick, watch, computed, Ref } from "vue";
import { useEventListener } from "@vueuse/core";
import type { Placement } from "element-plus";
import { cloneDeep } from "@pureadmin/utils";
import { IconJson } from "@/components/ReIcon/data";

type IconType = "ep:" | "fa:" | "fa-solid:";
interface IconTabType {
  label: string;
  name: IconType;
}
const tabsList: Array<IconTabType> = [
  {
    label: "Ele",
    name: "ep:"
  },
  {
    label: "Awe4",
    name: "fa:"
  },
  {
    label: "Awe5",
    name: "fa-solid:"
  }
];

interface Props {
  size?: "default" | "small" | "large";
  disabled?: boolean;
  title?: string;
  type?: IconType;
  placement?: Placement;
  modelValue?: string;
  showIconName?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
  size: "default",
  disabled: false,
  title: "",
  type: "ep:",
  placement: "bottom",
  modelValue: "",
  showIconName: false
});

const emits = defineEmits<{
  (e: "update:modelValue", value: string): void;
  (e: "change", value: string): void;
}>();

const selectorInput = ref();
const selectorScrollbarRef = ref();
const state: {
  iconType: IconType;
  selectorWidth: number;
  popoverVisible: boolean;
  inputFocus: boolean;
  iconSelectorMouseover: boolean;
  fontIconNames: string[];
  inputValue: string;
  prependIcon: string;
  defaultModelValue: string;
} = reactive({
  iconType: props.type,
  selectorWidth: 0,
  popoverVisible: false,
  inputFocus: false,
  iconSelectorMouseover: false,
  fontIconNames: [],
  inputValue: "",
  prependIcon: "",
  defaultModelValue: props.modelValue || "ep:document"
});

const onInputFocus = () => {
  state.inputFocus = state.popoverVisible = true;
};
const onInputBlur = () => {
  state.inputFocus = false;
  state.popoverVisible = state.iconSelectorMouseover;
};
const onInputRefresh = () => {
  // state.prependIcon = state.defaultModelValue;
  // state.inputValue = "";
  emits("update:modelValue", state.defaultModelValue);
  emits("change", state.defaultModelValue);
};

const iconList = ref(IconJson);
const currentActiveType: Ref<IconType> = ref("ep:");
// 深拷贝图标数据，前端做搜索
const copyIconList = cloneDeep(iconList.value);

// 搜索条件
const filterValue = ref("");

const pageList = computed<Array<string>>(() => {
  return copyIconList[currentActiveType.value].filter(v =>
    v.includes(filterValue.value)
  );
});
const onChangeTab = (name: IconType) => {
  currentActiveType.value = name;
};
const onIcon = (icon: string) => {
  state.iconSelectorMouseover = state.popoverVisible = false;
  state.iconType = currentActiveType.value;
  state.prependIcon = icon;
  filterValue.value = "";
  emits("update:modelValue", currentActiveType.value + icon);
  emits("change", currentActiveType.value + icon);
  nextTick(() => {
    selectorInput.value.blur();
  });
};

// 获取 input 的宽度
const getInputWidth = () => {
  nextTick(() => {
    state.selectorWidth =
      selectorInput.value.$el.offsetWidth < 260
        ? 260
        : selectorInput.value.$el.offsetWidth;
  });
};

const popoverVisible = () => {
  state.popoverVisible =
    state.inputFocus || state.iconSelectorMouseover ? true : false;
};

watch(
  () => props.modelValue,
  () => {
    if (props.modelValue) {
      currentActiveType.value =
        (props.modelValue.substring(
          0,
          props.modelValue.indexOf(":") + 1
        ) as IconType) || "ep:";
      state.iconType = props.modelValue.substring(
        0,
        props.modelValue.indexOf(":") + 1
      ) as IconType;
      state.prependIcon = props.modelValue.substring(
        props.modelValue.indexOf(":") + 1
      );
    }
  }
);
onMounted(() => {
  getInputWidth();
  useEventListener(document, "click", popoverVisible);
});
</script>

<style scoped lang="scss">
.size-small {
  height: 24px;
}
.size-large {
  height: 40px;
}
.size-default {
  height: 32px;
}
.icon-prepend {
  display: flex;
  align-items: center;
  justify-content: center;
  .name {
    padding-left: 5px;
  }
}
.selector-header {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
}
.selector-tab {
  margin-left: auto;
  span {
    padding: 0 5px;
    cursor: pointer;
    user-select: none;
    &.active,
    &:hover {
      color: var(--el-color-primary);
      text-decoration: underline;
    }
  }
}
.selector-body {
  height: 250px;
}
.icon-selector-item {
  display: inline-block;
  padding: 10px 10px 6px 10px;
  margin: 3px;
  border: 1px solid var(--ba-border-color);
  border-radius: var(--el-border-radius-base);
  cursor: pointer;
  font-size: 18px;
  .icon {
    height: 18px;
    width: 18px;
  }
  &:hover {
    border: 1px solid var(--el-color-primary);
  }
}
:deep(.el-input-group__prepend) {
  padding: 0 10px;
}
:deep(.el-input-group__append) {
  padding: 0 10px;
}
</style>
